import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeClassifier
import Orange
import numpy as np
import graphviz
from sklearn.tree import export_graphviz

from Orange.data.pandas_compat import table_from_frame

def GainRatio(df) :
    target_index = "Price"
    
    df[target_index] = df[target_index].astype('category')



    # Определите, какие столбцы представляют признаки (X), целевую переменную (y), и метаданные (если есть)
    xdf = df.drop('Price', axis=1)# Замените 'целевой_столбец' на название вашего целевого столбца
    ydf = df[['Price']]# Обернем целевой столбец в список для корректной передачи в Orange# Если у вас нет конкретного столбца для метаданных, используйте все столбцы как признаки (X)
    mdf = pd.DataFrame(index=df.index)

    orange_table = Orange.data.Table.from_pandas_dfs(xdf, ydf, mdf)

    target_index = "Price"

    #print(orange_table)

    if target_index is not None:

        # Используем метод из Orange для вычисления Gain Ratio
        gain_ratios = Orange.preprocess.score.GainRatio()(orange_table)

        # Выводим результаты
        for feature, gain_ratio in zip(orange_table.domain.attributes, gain_ratios):
            print(f"Feature: {feature.name}, Gain Ratio: {gain_ratio}")
    else:
        print("Целевой столбец не найден в домене.")

def C45(df) :
        
    # Выделите признаки и целевую переменную
    X = df.iloc[:, :-1]    
    y = df.iloc[:, -1]

    # Создайте классификатор дерева решений
    clf = DecisionTreeClassifier(criterion='entropy')  # Используем энтропию вместо Gini для Information Gain

    # Обучите модель
    clf.fit(X, y)

    print("Gain ratio для каждого признака:")
    for feature, importance in zip(X.columns, clf.feature_importances_):
        print(f"{feature}: {importance}")



    # Получите уникальные значения столбца Target в качестве меток классов
    class_names = y.unique().astype(str)
    # Экспортируйте структуру дерева в файл
    dot_data = export_graphviz(clf, out_file=None, feature_names=X.columns, class_names=class_names, filled=True, rounded=True)
    graph = graphviz.Source(dot_data)

    # Выведите граф дерева в формате PNG (или другом)
    graph.render("decision_tree") 

def CleanData(df) -> pd.DataFrame :
    """
    Очищает данные:
    1. замена пропущенных значений
    2. замена названий
    3. удаление дубликатов
    """

    numeric_columns = df.columns[1:]  # Все столбцы, начиная со второго

    # Замена пропущенных значений в столбцах на среднее значение
    df[numeric_columns] = df[numeric_columns].apply(lambda x: x.fillna(x.mean()))

    # Замена пропущенных значений в первом столбце на "неизвестно"
    df.iloc[:, 0] = df.iloc[:, 0].fillna("неизвестно")

    # Замена отсутствующие значения на среднее значение столбца:
    df.drop_duplicates(inplace=True)

    return df



# Загрузка данных из CSV файла
df = pd.read_csv('Laptop_price.csv')
print("Прочитано:\n", df, "\n")

df = CleanData(df)

print("После очистки:\n", df, "\n")

# Замена производителей на уникальный аутентификатор
df["Brand"] = pd.factorize(df["Brand"])[0]
#Замена вещественных 
#df.iloc[:, -1] = df.iloc[:, -1].round(-3)
df.iloc[:, -1] = df.iloc[:, -1] // 5000 * 5000

print("После замен:\n", df, "\n")

#print(df.iloc[:,-1])
for i in range(999) :
    print(df.iloc[i, -1])


# Построение тепловой карты с использованием seaborn
plt.figure(figsize=(10, 8))
sns.heatmap(df.corr(), annot=True, cmap='coolwarm', fmt=".3f", vmin=-1, vmax=1)
plt.title('Тепловая карта корреляции')
plt.show()



sym = input("Желаете удалить столбец?\n")
while (sym == 'y') :
    col=int(input("Какой столбец удалить?\n"))

    df = df.drop(df.columns[col-1], axis=1)

    plt.figure(figsize=(10, 8))
    sns.heatmap(df.corr(), annot=True, cmap='coolwarm', fmt=".3f", vmin=-1, vmax=1)
    plt.title('Тепловая карта корреляции')
    plt.show()

    sym = input("Желаете удалить столбец?\n")

GainRatio(df)
C45(df) 
